package tuan.core.extract;

import java.util.*;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import tuan.filter.*;
import tuan.utils.DomUtil;
import tuan.utils.RegUtil;
import tuan.utils.StringUtil;

public class PruductListExtract {
	Node root = null;
	String url;

	public PruductListExtract(Node root, String url) throws Exception {
		if (root == null || url == null) {
			throw new Exception("null arguments");
		}
		this.root = root;
		this.url = url;
	}

	/**
	 * 信息获取，返回商品LIST
	 * 
	 * @return
	 * @throws Exception
	 */
	public List<Product> extract() throws Exception {
		List<Node> titleNodeList = getTitleNodeList();
		Node pNode = DomUtil.getMinComParrent(titleNodeList);

		TravelFilterChain travelChain = new TravelFilterChain();
		travelChain.addFilter(new AllowdTagFilter(new String[] { "#text" }));
		travelChain.addFilter(new AllowdParentTagFilter(new String[] { "A" }));
		travelChain.addFilter(new TextLengthFiltter(5, ">"));

		DomUtil.postOrderTree(pNode, pNode, null, travelChain);
		List<Node> nodeList = travelChain.getNodeList();

		List<Product> productList = new ArrayList<Product>();
		Iterator<Node> iter = nodeList.iterator();
		while (iter.hasNext()) {
			Node titleNode = iter.next();
			Node unitNode = getUnitNode(pNode, titleNode);
			if (unitNode == null) {
				continue;
			}
			Product product = new Product();
			product.title = titleNode.getTextContent().trim();
			NamedNodeMap attrMap = titleNode.getParentNode().getAttributes();
			if (attrMap != null && attrMap.getNamedItem("title") != null) {
				String title = attrMap.getNamedItem("title").getTextContent().trim();
				if (title.length() > product.title.length()) {
					product.title = title;
				}
			}
			if (attrMap != null && attrMap.getNamedItem("href") != null) {
				product.url = StringUtil.getFullUrl(url, attrMap.getNamedItem("href").getNodeValue());
			}
			setImgUrl(unitNode, product);
			setPrice(unitNode, product);
			productList.add(product);
		}

		return productList;
	}

	/**
	 * 获取主打图片
	 * 
	 * @param node
	 * @param product
	 * @throws Exception
	 */
	void setImgUrl(Node node, Product product) throws Exception {
		TravelFilterChain travelChain = new TravelFilterChain();
		travelChain.addFilter(new AllowdTagFilter(new String[] { "IMG" }));
		travelChain.addFilter(new AllowdParentTagFilter(new String[] { "A" }));

		DomUtil.postOrderTree(node, node, null, travelChain);
		List<Node> nodeList = travelChain.getNodeList();

		if (nodeList.size() > 0) {
			NamedNodeMap attrMap = nodeList.get(0).getAttributes();
			if (attrMap.getNamedItem("src") != null) {
				String src = attrMap.getNamedItem("src").getNodeValue();
				product.imgList.add(StringUtil.getFullUrl(url, src));
			}
		}
	}

	/**
	 * 获取现价，原价，节省
	 * 
	 * @param node
	 * @param product
	 * @throws Exception
	 */
	void setPrice(Node node, Product product) throws Exception {
		TravelFilterChain travelChain = new TravelFilterChain();
		travelChain.addFilter(new AllowdTagFilter(new String[] { "#text" }));
		travelChain.addFilter(new NotAllowdParentTagFilter(new String[] { "A" }));
		travelChain.addFilter(new TextLengthFiltter(20, "<"));

		DomUtil.postOrderTree(node, node, null, travelChain);
		List<Node> nodeList = travelChain.getNodeList();

		Iterator<Node> iter = nodeList.iterator();
		String text = "";
		while (iter.hasNext()) {
			Node textNode = iter.next();
			String nodeText = StringUtil.getPureText(textNode.getTextContent());
			nodeText = nodeText.replaceAll("[\\s¥￥元:：]", "");
			text += nodeText;
			if (nodeText.length() > 0) {
				char ch = nodeText.charAt(nodeText.length() - 1);
				if (ch >= '0' && ch <= '9') {
					text += " ";
				}
			}
		}
		String regPattern = "(\\d+)\\s*[^0-9]{0,3}购买";
		String retstr = RegUtil.getGroup1(regPattern, text);
		if (retstr != null && product.buyNum.length() == 0) {
			product.buyNum = retstr;
			text = RegUtil.deleteGroup1(regPattern, text);
		}

		regPattern = "原价[^0-9]{0,20}(\\d+(\\.\\d+)?)";
		retstr = RegUtil.getGroup1(regPattern, text);
		if (retstr != null) {
			product.oldPrice = retstr;
			text = RegUtil.deleteGroup1(regPattern, text);
		} else {
			regPattern = "市场价[^0-9]{0,20}(\\d+(\\.\\d+)?)";
			retstr = RegUtil.getGroup1(regPattern, text);
			text = RegUtil.deleteGroup1(regPattern, text);
			if (retstr != null) {
				product.oldPrice = retstr;
				text = RegUtil.deleteGroup1(regPattern, text);
			}
		}

		regPattern = "现价[^0-9]{0,20}(\\d+(\\.\\d+)?)";
		retstr = RegUtil.getGroup1(regPattern, text);
		if (retstr != null) {
			product.nowPrice = retstr;
			text = RegUtil.deleteGroup1(regPattern, text);
		}

		regPattern = "节省[^0-9]{0,20}(\\d+(\\.\\d+)?)";
		retstr = RegUtil.getGroup1(regPattern, text);
		if (retstr != null) {
			product.savePrice = retstr;
			text = RegUtil.deleteGroup1(regPattern, text);
		}

		regPattern = "折扣[^0-9]{0,20}(\\d+(\\.\\d+)?)";
		retstr = RegUtil.getGroup1(regPattern, text);
		if (retstr != null) {
			product.discount = retstr;
			text = RegUtil.deleteGroup1(regPattern, text);
		}
	}

	/**
	 * 获取产品最小单元根节点
	 * 
	 * @param root
	 * @param titleNode
	 * @return
	 */
	Node getUnitNode(Node root, Node titleNode) {
		while (titleNode.getParentNode() != null && !titleNode.getParentNode().equals(root)) {
			titleNode = titleNode.getParentNode();
		}
		return titleNode;
	}

	/**
	 * 标题节点识别
	 * 
	 * @return
	 * @throws Exception
	 */
	List<Node> getTitleNodeList() throws Exception {
		/*
		 * 标题链接识别： 1、筛选出带连接的文本节点，过滤字数少于10的节点 2、选取包含最大文字数的style 3、过滤掉非style的节点
		 * 4、剩下的即为标题
		 */
		TravelFilterChain travelChain = new TravelFilterChain();
		travelChain.addFilter(new AllowdTagFilter(new String[] { "#text" }));
		travelChain.addFilter(new AllowdParentTagFilter(new String[] { "A" }));
		travelChain.addFilter(new TextLengthFiltter(10, ">"));

		DomUtil.postOrderTree(root, root, null, travelChain);
		List<Node> nodeList = travelChain.getNodeList();

		DomUtil.setTextNodeFont(nodeList);
		Object maxAttrValue = DomUtil.getMaxTextAttr(nodeList, "style");

		NodeListFilterChain nodeListChain = new NodeListFilterChain();
		nodeListChain.addFilter(new AllowdAttrFilter("style", maxAttrValue));
		nodeList = nodeListChain.filter(nodeList);

		return nodeList;
	}
}
